<html>
<head>
  <title>Evernote Export</title>
  <basefont face="微软雅黑" size="2" />
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  <meta name="exporter-version" content="Evernote Windows/304720 (zh-CN, DDL); Windows/10.0.14393 (Win64);"/>
  <style>
    body, td {
      font-family: 微软雅黑;
      font-size: 10pt;
    }
  </style>
</head>
<body>
<a name="3273"/>
<h1>6、SpringMVC源码</h1>
<div>
<table bgcolor="#D4DDE5" border="0">
<tr><td><b>创建时间：</b></td><td><i>2017/6/20 11:43</i></td></tr>
<tr><td><b>更新时间：</b></td><td><i>2017/6/20 17:21</i></td></tr>
<tr><td><b>作者：</b></td><td><i>雷丰阳</i></td></tr>
</table>
</div>
<br/>

<div>
<span><div>1、前端控制器的架构？DispatcherServlet；</div><div>          <img src="6、SpringMVC源码_files/Image.png" type="image/png" style="height: auto;"/></div><div>2、doDispatch()详细细节：</div><div><br/></div><div align="left" style="min-height: 18pt;"><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>protected</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>void</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">doDispatch(HttpServletRequest request, HttpServletResponse response)</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>throws</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">Exception {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        HttpServletRequest processedRequest = request;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        HandlerExecutionChain mappedHandler =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>boolean</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">multipartRequestParsed =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>false</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        WebAsyncManager asyncManager = WebAsyncUtils.</span><span style="font-size:16pt"><i>getAsyncManager</i></span><span style="font-size:16pt">(request);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>try</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">{</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            ModelAndView mv =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            Exception dispatchException =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>try</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">{</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">               <span style="color: rgb(255, 70, 53);">//1、检查是否文件上传请求</span></span></span></div></div><div align="left" style="min-height: 18pt;"><span style="color: rgb(255, 70, 53);"><font face="Consolas" size="4"><span style="font-size:16pt">                processedRequest = checkMultipart(request);</span></font></span></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                multipartRequestParsed = processedRequest != request;</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#3F7F5F" face="Consolas" size="4"><span style="font-size:16pt">// Determine handler for the current request.</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(63, 127, 95);">              <span style="color: rgb(156, 0, 76);"> //2、根据当前的请求地址找到那个类能来处理；</span></span></span></span></div></div><div align="left" style="min-height: 18pt;"><div><span style="color: rgb(156, 0, 76);"><font face="Consolas" size="4"><span style="font-size:16pt">                mappedHandler = getHandler(processedRequest);</span></font></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><br/></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">              <span style="color: rgb(227, 0, 0);"> //3、如果没有找到哪个处理器（控制器）能处理这个请求就404，或者抛异常</span></span></span></div></div><div align="left" style="min-height: 18pt;"><span style="color: rgb(227, 0, 0);"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(mappedHandler ==</span></font> <font face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">|| mappedHandler.getHandler() ==</span></font> <font face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">) {</span></font></span></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    noHandlerFound(processedRequest, response);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>return</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><br/></span></span></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#3F7F5F" face="Consolas" size="4"><span style="font-size:16pt">// Determine handler adapter for the current request.</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(63, 127, 95);">               <span style="color: rgb(227, 0, 0);">//4、拿到能执行这个类的所有方法的适配器；（反射工具</span></span></span></span><font color="#010101" face="Consolas" size="4"><span style="font-size:16pt">AnnotationMethodHandlerAdapter</span></font><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(63, 127, 95);"><span style="color: rgb(227, 0, 0);">）</span></span></span></span></div></div><div align="left" style="min-height: 18pt;"><span style="color: rgb(227, 0, 0);"><font face="Consolas" size="4"><span style="font-size:16pt">                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());</span></font></span></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#3F7F5F" face="Consolas" size="4"><span style="font-size:16pt">// Process last-modified header, if supported by the handler.</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                String method = request.getMethod();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>boolean</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">isGet =</span></font> <font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;GET&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.equals(method);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(isGet ||</span></font> <font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;HEAD&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.equals(method)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>long</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">lastModified = ha.getLastModified(request, mappedHandler.getHandler());</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">logger</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isDebugEnabled()) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        String requestUri =</span></font> <font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt"><i>urlPathHelper</i></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.getRequestUri(request);</span></font></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        </span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">logger</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.debug(</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;Last-Modified value for [&quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+ requestUri +</span></font> <font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;] is: &quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+ lastModified);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>new</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">ServletWebRequest(request, response).checkNotModified(lastModified) &amp;&amp; isGet) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>return</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(!mappedHandler.applyPreHandle(processedRequest, response)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>return</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>try</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">{</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#3F7F5F" face="Consolas" size="4"><span style="font-size:16pt">// Actually invoke the handler.处理（控制）器的方法被调用</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(63, 127, 95);">                    //控制器（Controller），处理器（Handler）</span></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(63, 127, 95);">                    //5、适配器来执行目标方法；将目标方法执行完成后的返回值作为视图名，设置保存到ModelAndView中</span></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(63, 127, 95);">                    //目标方法无论怎么写，最终适配器执行完成以后都会将执行后的信息封装成ModelAndView<br/></span></span></span></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                   <span style="color: rgb(227, 0, 0);"> mv = ha.handle(processedRequest, response, mappedHandler.getHandler());</span></span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>finally</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">{</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(asyncManager.isConcurrentHandlingStarted()) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>return</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    }</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">                applyDefaultViewName(request, mv);//如果没有视图名设置一个默认的视图名；</span></font></div></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                mappedHandler.applyPostHandle(processedRequest, response, mv);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>catch</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(Exception ex) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                dispatchException = ex;</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">            //转发到目标页面；</span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">            //6、根据方法最终执行完成后封装的ModelAndView；转发到对应页面，而且</span></span><span style="font-size: 16pt;"><span style="font-family: Consolas;">ModelAndView中的数据可以从请求域中获取</span></span></div></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span><span style="color: rgb(227, 0, 0);"><span style="font-size:16pt; background:#d4d4d4">processDispatchResult</span><span style="font-size:16pt">(processedRequest, response, mappedHandler, mv, dispatchException);</span></span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>catch</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(Exception ex) {</span></font></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>catch</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(Error err) {</span></font></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>finally</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">{</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(asyncManager.isConcurrentHandlingStarted()) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#3F7F5F" face="Consolas" size="4"><span style="font-size:16pt">// Instead of postHandle and afterCompletion</span></font></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>return</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#3F7F5F" face="Consolas" size="4"><span style="font-size:16pt">// Clean up any resources used by a multipart request.</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(multipartRequestParsed) {</span></font></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                cleanupMultipart(processedRequest);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        }</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    }</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><br/></span></span></div><div><hr/></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">1)、所有请求过来DispatcherServlet收到请求，</span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">2）、调用doDispatch()方法进行处理</span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">          1）、getHandler()：根据当前请求地址找到能处理这个请求的目标处理器类（处理器）</span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">                    根据当前请求在HandlerMapping中找到这个请求的映射信息，获取到目标处理器类<br/></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">          2）、</span></span><span style="color: rgb(227, 0, 0);"><font face="Consolas" size="4"><span style="font-size:16pt">getHandlerAdapter()：根据当前处理器类获取到能执行这个处理器方法的适配器；</span></font></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(227, 0, 0);">                   </span> 根据当前处理器类，找到当前类的HandlerAdapter（适配器）<br/></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(227, 0, 0);">          3）、使用刚才获取到的适配器（</span></span></span><font color="#010101" face="Consolas" size="4"><span style="font-size:16pt">AnnotationMethodHandlerAdapter</span></font> <span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(227, 0, 0);">）执行目标方法;</span></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(227, 0, 0);">          4）、目标方法执行后会返回一个ModelAndView对象</span></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(227, 0, 0);">          5）、根据</span></span></span><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(227, 0, 0);">ModelAndView的信息转发到具体的页面，并可以在请求域中取出ModelAndView中的模型数据</span></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(227, 0, 0);"><br/></span></span></span></div><div><hr/></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(227, 0, 0);">三、</span></span></span><span style="font-size: 16pt;"><span style="font-family: Consolas;">getHandler()细节：怎么根据当前请求就能找到哪个类能来处理</span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">getHandler()会返回目标处理器类的执行链；</span></span></div><div><img src="6、SpringMVC源码_files/Image [1].png" type="image/png"/>；</div><div><br/></div><div>HandlerMapping：处理器映射：他里面保存了每一个处理器能处理哪些请求的映射信息；</div><div><img src="6、SpringMVC源码_files/Image [2].png" type="image/png"/></div><div><br/></div><div><br/></div><div>handlerMap：ioc容器启动创建Controller对象的时候扫描每个处理器都能处理什么请求，保存在HandlerMapping的handlerMap属性中；</div><div>下一次请求过来，就来看哪个HandlerMapping中有这个请求映射信息就行了；</div><div><img src="6、SpringMVC源码_files/Image [3].png" type="image/png"/></div><div><br/></div><div><br/></div><div><br/></div><div align="left" style="min-height: 18pt;"><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>protected</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">HandlerExecutionChain</span> <span style="font-size:16pt; background:#d4d4d4">getHandler</span><span style="font-size:16pt">(HttpServletRequest request)</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>throws</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">Exception {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae"><b>for</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">(HandlerMapping hm :</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae"><b>this</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">.</span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">handlerMappings</span></font><font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">logger</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isTraceEnabled()) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">logger</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.trace(</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        </span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;Testing handler map [&quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+ hm +</span></font> <font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;] in DispatcherServlet with name '&quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+ getServletName() +</span></font> <font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;'&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            HandlerExecutionChain handler = hm.getHandler(request);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(handler !=</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>return</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">handler;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>return</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    }</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><br/></span></span></div><div><hr/></div><div align="left" style="min-height: 18pt;"><div><b><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(127, 0, 85);">4、如何找到目标处理器类的适配器。要拿适配器才去执行目标方法</span></span></span></b></div><div><img src="6、SpringMVC源码_files/Image [4].png" type="image/png"/></div><div><br/></div><div><span style="font-size: 21px;"><b>AnnotationMethodHandlerAdapter</b>：能解析注解方法的适配器；</span></div><div><span style="font-size: 21px;">处理器类中只要有标了注解的这些方法就能用；</span></div><div><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>protected</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">HandlerAdapter getHandlerAdapter(Object handler)</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>throws</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">ServletException {</span></font></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae"><b>for</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">(HandlerAdapter ha :</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae"><b>this</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">.</span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">handlerAdapters</span></font><font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">logger</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isTraceEnabled()) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">logger</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.trace(</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;Testing handler adapter [&quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+ ha +</span></font> <font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;]&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(ha.supports(handler)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>return</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">ha;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>throw</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>new</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">ServletException(</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;No adapter for handler [&quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+ handler +</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">);</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    }</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><br/></span></span></div><div><hr/></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">5、DispatcherServlet中有几个引用类型的属性；SpringMVC的九大组件；</span></span></div><div><font face="Consolas"><span style="font-size: 21px;">SpringMVC在工作的时候，关键位置都是由这些组件完成的；</span></font></div><div><font face="Consolas"><span style="font-size: 21px;">共同点：九大组件全部都是接口；接口就是规范；提供了非常强大的扩展性；</span></font></div><div><font face="Consolas"><span style="font-size: 21px; line-height: 30px;">SpringMVC的九大组件工作原理；</span></font></div><div><span style="font-size: 21px;"><span style="font-family: Consolas;"><br/></span></span></div><div align="left" style="min-height: 18pt;"><div><font color="#3F5FBF" face="Consolas" size="4"><span style="font-size:16pt">     /** 文件上传解析器*/</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>private</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">MultipartResolver</span></font> <font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">multipartResolver</span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#3F5FBF" face="Consolas" size="4"><span style="font-size:16pt">/** 区域信息解析器；和国际化有关 */</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>private</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">LocaleResolver</span></font> <font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">localeResolver</span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#3F5FBF" face="Consolas" size="4"><span style="font-size:16pt">/** 主题解析器；强大的主题效果更换 */</span></font></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>private</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">ThemeResolver</span></font> <font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">themeResolver</span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#3F5FBF" face="Consolas" size="4"><span style="font-size:16pt">/** Handler映射信息；</span></font><font face="Consolas" size="4"><span style="font-size:16pt">HandlerMapping</span></font> <font color="#3F5FBF" face="Consolas" size="4"><span style="font-size:16pt">*/</span></font></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>private</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">List&lt;HandlerMapping&gt;</span></font> <font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">handlerMappings</span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#3F5FBF" face="Consolas" size="4"><span style="font-size:16pt">/** Handler的适配器 */</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>private</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">List&lt;HandlerAdapter&gt;</span></font> <font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">handlerAdapters</span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#3F5FBF" face="Consolas" size="4"><span style="font-size:16pt">/** SpringMVC强大的异常解析功能；异常解析器 */</span></font></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>private</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">List&lt;HandlerExceptionResolver&gt;</span></font> <font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">handlerExceptionResolvers</span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#3F5FBF" face="Consolas" size="4"><span style="font-size:16pt">/** </span></font> <font color="#3F5FBF" face="Consolas" size="4"><span style="font-size:16pt">*/</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>private</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">RequestToViewNameTranslator</span></font> <font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">viewNameTranslator</span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#3F5FBF" face="Consolas" size="4"><span style="font-size:16pt">/** </span></font><font face="Consolas" size="4"><span style="font-size:16pt">FlashMap+Manager：SpringMVC中运行重定向携带数据的功能</span></font> <font color="#3F5FBF" face="Consolas" size="4"><span style="font-size:16pt">*/</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>private</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">FlashMapManager</span></font> <font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">flashMapManager</span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#3F5FBF" face="Consolas" size="4"><span style="font-size:16pt">/** 视图解析器； */</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>private</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">List&lt;ViewResolver&gt;</span></font> <font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">viewResolvers</span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div></div></div></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><br/></span></span></div><div><hr/></div><div><font face="Consolas"><span style="font-size: 21px;">DispatcherServlet中九大组件初始化的地方：</span></font></div><div align="left" style="min-height: 18pt;"><div style="-en-codeblock: true; box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial;"><div>protected void initStrategies(ApplicationContext context) {</div><div>        initMultipartResolver(context);</div><div>        initLocaleResolver(context);</div><div>        initThemeResolver(context);</div><div>        <span style="color: rgb(227, 0, 0);">initHandlerMappings(context);</span></div><div>        <span style="color: rgb(227, 0, 0);">initHandlerAdapters(context);</span></div><div>        initHandlerExceptionResolvers(context);</div><div>        initRequestToViewNameTranslator(context);</div><div>        initViewResolvers(context);</div><div>        initFlashMapManager(context);</div><div>    }</div></div><div><span style="font-size: 16pt;"><br/></span></div><div><br/></div><div style="-en-codeblock: true; box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial;"><div>可以在web.xml中修改DispatcherServlet某些属性的默认配置；</div><div>&lt;init-param&gt;</div><div>            &lt;param-name&gt;detectAllHandlerMappings&lt;/param-name&gt;</div><div>            &lt;param-value&gt;false&lt;/param-value&gt;</div><div>        &lt;/init-param&gt;</div></div><div><br/></div></div><div align="left" style="min-height: 18pt;"><div><span style="font-size: 21px; line-height: 30px;">初始化HandlerMapping</span></div><div style="-en-codeblock: true; box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial;"><div>private void initHandlerMappings(ApplicationContext context) {</div><div>        this.handlerMappings = null;</div><div><br/></div><div>        if (this.detectAllHandlerMappings) {</div><div>            // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.</div><div>            Map&lt;String, HandlerMapping&gt; matchingBeans =</div><div>                    BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);</div><div>            if (!matchingBeans.isEmpty()) {</div><div>                this.handlerMappings = new ArrayList&lt;HandlerMapping&gt;(matchingBeans.values());</div><div>                // We keep HandlerMappings in sorted order.</div><div>                OrderComparator.sort(this.handlerMappings);</div><div>            }</div><div>        }</div><div>        else {</div><div>            try {</div><div>                HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);</div><div>                this.handlerMappings = Collections.singletonList(hm);</div><div>            }</div><div>            catch (NoSuchBeanDefinitionException ex) {</div><div>                // Ignore, we'll add a default HandlerMapping later.</div><div>            }</div><div>        }</div><div><br/></div><div>        // Ensure we have at least one HandlerMapping, by registering</div><div>        // a default HandlerMapping if no other mappings are found.</div><div>        if (this.handlerMappings == null) {</div><div>            this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);</div><div>            if (logger.isDebugEnabled()) {</div><div>                logger.debug(&quot;No HandlerMappings found in servlet '&quot; + getServletName() + &quot;': using default&quot;);</div><div>            }</div><div>        }</div><div>    }</div></div><div><span style="font-size: 21px;">组件的初始化：</span></div><div><span style="font-size: 21px;">     有些组件在容器中是使用类型找的，有些组件是使用id找的；<br/></span></div><div><span style="font-size: 21px;">     去容器中找这个组件，如果没有找到就用默认的配置；</span></div><div><span style="font-size: 21px;"><br/></span></div><div><hr/></div><div align="left" style="min-height: 18pt;"><div><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>public</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">String updateBook(</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">@RequestParam</span></font><font face="Consolas" size="4"><span style="font-size:16pt">(value=</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;author&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">)String author,</span></font><font face="Consolas" size="4"><span style="font-size:16pt">Map&lt;String, Object&gt; model,</span></font></div><div><font face="Consolas" size="4"><span style="font-size:16pt">                      HttpServletRequest request,</span></font><font face="Consolas" size="4"><span style="font-size:16pt"> </span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">@</span><span style="font-size:16pt; background:#d4d4d4">ModelAttribute</span></font><font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;haha&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">)Book book</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">            )</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><br/></span></span></div></div><div><font face="Consolas" size="4"><span style="font-size:16pt"><span style="color: rgb(227, 0, 0);">mv = ha.handle(processedRequest, response, mappedHandler.getHandler());执行目标方法的细节；</span></span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(227, 0, 0);">     ||</span></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="color: rgb(227, 0, 0);">     \/<br/></span></span></span></div><div align="left" style="min-height: 18pt;"><div><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae"><b>return</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">invokeHandlerMethod(request, response, handler);</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="background-color: rgb(198, 219, 174);">     ||</span></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="background-color: rgb(198, 219, 174);">     \/<br/></span></span></span></div><div align="left" style="min-height: 18pt;"><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>protected</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>throws</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">Exception {</span></font></div></div><div align="left" style="min-height: 18pt;"><div>                           //拿到方法的解析器</div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">        ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">          //方法解析器根据当前请求地址找到真正的目标方法<br/></span></span></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">        Method handlerMethod = methodResolver.resolveHandlerMethod(request);</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">          //创建一个方法执行器；<br/></span></span></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">        ServletHandlerMethodInvoker methodInvoker =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>new</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">ServletHandlerMethodInvoker(methodResolver);</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">          //包装原生的</span></span><font face="Consolas" size="4"><span style="font-size:16pt">request, response，</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">        ServletWebRequest webRequest =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>new</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">ServletWebRequest(request, response);</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">        <b><span style="color: rgb(227, 0, 0);">  //创建了一个，隐含模型</span></b></span></span></div></div><div align="left" style="min-height: 18pt;"><b><span style="color: rgb(227, 0, 0);"><font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">        ExtendedModelMap implicitModel =</span></font> <font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">new</span></font> <font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">BindingAwareModelMap();</span></font></span></b></div><div align="left" style="min-height: 18pt;"><div><br/></div></div><div align="left" style="min-height: 18pt;"><div>                         //真正执行目标方法；目标方法利用反射执行期间确定参数值，提前执行modelattribute等所有的操作都在这个方法中；</div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">       <span style="color: rgb(65, 173, 28);"> <b>Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest,</b></span></span> <span style="color: rgb(65, 173, 28);"><b><span style="color: rgb(227, 0, 0);"><span style="font-size:16pt; background:#d4d4d4">implicitModel</span></span><span style="font-size:16pt">);</span></b></span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        ModelAndView mav =</span></font></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result,</span> <span style="font-size:16pt; background:#d4d4d4">implicitModel</span><span style="font-size:16pt">, webRequest);</span></font></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        methodInvoker.updateModelAttributes(handler, (mav !=</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">? mav.getModel() :</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">),</span> <span style="font-size:16pt; background:#d4d4d4">implicitModel</span><span style="font-size:16pt">, webRequest);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>return</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">mav;</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    }</span></font></div></div></div></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><br/></span></span></div><div><hr/></div><div align="left" style="min-height: 18pt;"><div><font color="#7F0055" face="Consolas"><span style="font-size: 21px;"><b>方法执行的细节</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt; background:#d4d4d4">invokeHandlerMethod</span></font></div><div><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>public</b></span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>final</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">Object</span> <span style="font-size:16pt; background:#d4d4d4">invokeHandlerMethod</span><span style="font-size:16pt">(Method handlerMethod, Object handler,</span></font></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            NativeWebRequest webRequest, ExtendedModelMap implicitModel)</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>throws</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">Exception {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">        Method handlerMethodToInvoke = BridgeMethodResolver.</span><span style="font-size:16pt; background:#c6dbae"><i>findBridgedMethod</i></span><span style="font-size:16pt; background:#c6dbae">(handlerMethod);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>try</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">{</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>boolean</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">debug =</span></font> <font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt"><i>logger</i></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isDebugEnabled();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>for</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(String attrName :</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>this</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.</span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">methodResolver</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.getActualSessionAttributeNames()) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                Object attrValue =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>this</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.</span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">sessionAttributeStore</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.retrieveAttribute(webRequest, attrName);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(attrValue !=</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">) {</span></font></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    implicitModel.addAttribute(attrName, attrValue);</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">               </span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">          //找到所有@ModelAttribute注解标注的方法；<br/></span></span></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">           <span style="color: rgb(227, 0, 0);"><b> </b></span></span></font><span style="color: rgb(227, 0, 0);"><b><font face="Consolas" size="4"><span style="font-size:16pt">for</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(Method attributeMethod :</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">this</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.</span></font><font face="Consolas" size="4"><span style="font-size:16pt">methodResolver</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.getModelAttributeMethods()) {</span></font></b></span></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">                Method attributeMethodToInvoke = BridgeMethodResolver.</span><span style="font-size:16pt"><i>findBridgedMethod</i></span><span style="font-size:16pt">(attributeMethod);</span></font></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">                //先确定modelattribute方法执行时要使用的每一个参数的值；</span></font></div><div><font face="Consolas" size="4"><span style="font-size:16pt"><span style="color: rgb(227, 0, 0);">               Object[] args = <b><span style="color: rgb(45, 79, 201);">resolveHandlerArguments</span></b>(attributeMethodToInvoke, handler, webRequest, <b><span style="color: rgb(45, 79, 201);">implicitModel</span></b>);</span></span></font></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(debug) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt"><i>logger</i></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.debug(</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;Invoking model attribute method: &quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+ attributeMethodToInvoke);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                String attrName = AnnotationUtils.</span><span style="font-size:16pt"><i>findAnnotation</i></span><span style="font-size:16pt">(attributeMethod,</span></font> <font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">ModelAttribute</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">).value();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(!</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.equals(attrName) &amp;&amp; implicitModel.containsAttribute(attrName)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>continue</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 11pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">                ReflectionUtils.</span><span style="font-size:16pt"><i>makeAccessible</i></span><span style="font-size:16pt">(attributeMethodToInvoke);</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">               </span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">              <span style="color: rgb(227, 0, 0);"> //提前运行ModelAttribute，</span></span></span></div></div><div align="left" style="min-height: 18pt;"><span style="color: rgb(227, 0, 0);"><font face="Consolas" size="4"><span style="font-size:16pt">                <b>Object attrValue = attributeMethodToInvoke.invoke(handler, args);</b></span></font></span></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.equals(attrName)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    Class&lt;?&gt; resolvedType = GenericTypeResolver.</span><span style="font-size:16pt"><i>resolveReturnType</i></span><span style="font-size:16pt">(attributeMethodToInvoke, handler.getClass());</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    attrName = Conventions.</span><span style="font-size:16pt"><i>getVariableNameForReturnType</i></span><span style="font-size:16pt">(attributeMethodToInvoke, resolvedType, attrValue);</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">              <span style="color: rgb(227, 0, 0);">  //把提前运行的ModelAttribute方法的返回值也放在隐含模型中</span></span></span></div></div><div align="left" style="min-height: 18pt;"><span style="color: rgb(227, 0, 0);"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(!implicitModel.containsAttribute(attrName)) {</span></font></span></div><div align="left" style="min-height: 11pt;"><span style="color: rgb(227, 0, 0);"><font face="Consolas" size="4"><span style="font-size:16pt">                    implicitModel.addAttribute(attrName, attrValue);</span></font></span></div><div align="left" style="min-height: 18pt;"><span style="color: rgb(227, 0, 0);"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></span></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><br/></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">              <span style="color: rgb(227, 0, 0);"> //再次解析目标方法参数是哪些值</span></span></span></div></div><div align="left" style="min-height: 18pt;"><span style="color: rgb(227, 0, 0);"><font face="Consolas" size="4"><span style="font-size:16pt">            <b>Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);</b></span></font></span></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(debug) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt"><i>logger</i></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.debug(</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;Invoking request handler method: &quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+ handlerMethodToInvoke);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 11pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">            ReflectionUtils.</span><span style="font-size:16pt"><i>makeAccessible</i></span><span style="font-size:16pt">(handlerMethodToInvoke);</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><br/></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">            <span style="color: rgb(227, 0, 0);">//执行目标方法</span></span></span></div></div><div align="left" style="min-height: 18pt;"><span style="color: rgb(227, 0, 0);"><font face="Consolas" size="4"><span style="font-size:16pt">           <b> </b></span></font><b><font face="Consolas" size="4"><span style="font-size:16pt">return</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">handlerMethodToInvoke.invoke(handler, args);</span></font></b></span></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>catch</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(IllegalStateException ex) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#3F7F5F" face="Consolas" size="4"><span style="font-size:16pt">// Internal assertion failed (e.g. invalid signature):</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#3F7F5F" face="Consolas" size="4"><span style="font-size:16pt">// throw exception with full handler method context...</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>throw</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>new</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">HandlerMethodInvocationException(handlerMethodToInvoke, ex);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>catch</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(InvocationTargetException ex) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#3F7F5F" face="Consolas" size="4"><span style="font-size:16pt">// User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...</span></font></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            ReflectionUtils.</span><span style="font-size:16pt"><i>rethrowException</i></span><span style="font-size:16pt">(ex.getTargetException());</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>return</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        }</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    }</span></font></div></div></div><div><br/></div><div><hr/></div><div align="left" style="min-height: 18pt;"><div><font color="#010101" face="Consolas" size="4"><span style="font-size:16pt">public java.lang.String com.atguigu.controller.ModelAttributeTestController.updateBook(</span></font></div><div><font color="#010101" face="Consolas" size="4"><span style="font-size:16pt">java.lang.String,</span></font></div><div><font color="#010101" face="Consolas" size="4"><span style="font-size:16pt">java.util.Map,</span></font></div><div><font color="#010101" face="Consolas" size="4"><span style="font-size:16pt">javax.servlet.http.HttpServletRequest,</span></font></div><div><font color="#010101" face="Consolas" size="4"><span style="font-size:16pt">com.atguigu.bean.Book)</span></font></div></div><div><br/></div><div><hr/></div><div align="left" style="min-height: 18pt;"><div><font color="#7F0055" face="Consolas"><span style="font-size: 21px; line-height: 30px;"><b>确定方法运行时使用的每一个参数的值</b></span></font></div><div><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>private</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt"><span style="color: rgb(45, 79, 201);">Object[]</span> <span style="color: rgb(227, 0, 0);"><b>resolveHandlerArguments</b></span>(Method handlerMethod, Object handler,</span></font></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            NativeWebRequest webRequest, ExtendedModelMap implicitModel)</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>throws</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">Exception {</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">        Class&lt;?&gt;[] paramTypes = handlerMethod.getParameterTypes();</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">          //创建了一个和参数个数一样多的数组，会用来保存每一个参数的值<br/></span></span></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">        Object[] args =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae"><b>new</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">Object[paramTypes.</span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">length</span></font><font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">];</span></font></div><div align="left" style="min-height: 18pt;"><br/></div><div align="left" style="min-height: 18pt;"><div>                      </div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>for</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>int</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">i = 0; i &lt;</span> <span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">.</span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">length</span></font><font face="Consolas" size="4"><span style="font-size:16pt">; i++) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            MethodParameter methodParam =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>new</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">MethodParameter(handlerMethod, i);</span></font></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            methodParam.initParameterNameDiscovery(</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>this</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.</span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">parameterNameDiscoverer</span></font><font face="Consolas" size="4"><span style="font-size:16pt">);</span></font></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            GenericTypeResolver.</span><span style="font-size:16pt"><i>resolveParameterType</i></span><span style="font-size:16pt">(methodParam, handler.getClass());</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            String paramName =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            String headerName =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>boolean</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">requestBodyFound =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>false</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            String cookieName =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            String pathVarName =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            String attrName =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>boolean</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">required =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>false</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            String defaultValue =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>boolean</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">validate =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>false</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            Object[] validationHints =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>int</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">annotationsFound = 0;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            Annotation[] paramAnns = methodParam.getParameterAnnotations();</span></font></div><div align="left" style="min-height: 18pt;"><div>                                     <span style="font-size: 21px;"> //找到目标方法这个参数的所有注解，如果有注解就解析并保存注解的信息；</span></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>for</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(Annotation paramAnn : paramAnns) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">RequestParam</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isInstance(paramAnn)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">RequestParam</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">requestParam = (</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">RequestParam</span></font><font face="Consolas" size="4"><span style="font-size:16pt">) paramAnn;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    paramName = requestParam.value();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    required = requestParam.required();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    annotationsFound++;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">RequestHeader</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isInstance(paramAnn)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">RequestHeader</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">requestHeader = (</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">RequestHeader</span></font><font face="Consolas" size="4"><span style="font-size:16pt">) paramAnn;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    headerName = requestHeader.value();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    required = requestHeader.required();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue());</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    annotationsFound++;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">RequestBody</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isInstance(paramAnn)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    requestBodyFound =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>true</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    annotationsFound++;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">CookieValue</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isInstance(paramAnn)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">CookieValue</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">cookieValue = (</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">CookieValue</span></font><font face="Consolas" size="4"><span style="font-size:16pt">) paramAnn;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    cookieName = cookieValue.value();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    required = cookieValue.required();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    defaultValue = parseDefaultValueAttribute(cookieValue.defaultValue());</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    annotationsFound++;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">PathVariable</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isInstance(paramAnn)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">PathVariable</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">pathVar = (</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">PathVariable</span></font><font face="Consolas" size="4"><span style="font-size:16pt">) paramAnn;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    pathVarName = pathVar.value();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    annotationsFound++;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">ModelAttribute</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isInstance(paramAnn)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">ModelAttribute</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">attr = (</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">ModelAttribute</span></font><font face="Consolas" size="4"><span style="font-size:16pt">) paramAnn;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    attrName = attr.value();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    annotationsFound++;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">Value</span></font><font face="Consolas" size="4"><span style="font-size:16pt">.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isInstance(paramAnn)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    defaultValue = ((</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">Value</span></font><font face="Consolas" size="4"><span style="font-size:16pt">) paramAnn).value();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(paramAnn.annotationType().getSimpleName().startsWith(</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;Valid&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    validate =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>true</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    Object value = AnnotationUtils.</span><span style="font-size:16pt"><i>getValue</i></span><span style="font-size:16pt">(paramAnn);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    validationHints = (value</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>instanceof</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">Object[] ? (Object[]) value :</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>new</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">Object[] {value});</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(annotationsFound &gt; 1) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>throw</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>new</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">IllegalStateException(</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;Handler parameter annotations are exclusive choices - &quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        </span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;do not specify more than one such annotation on the same parameter: &quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+ handlerMethod);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><div><br/></div></div><div align="left" style="min-height: 18pt;"><div>                                  <span style="font-size: 21px;"> //没有找到注解的情况；</span></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(annotationsFound == 0) {</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">                //解析普通参数<br/></span></span></div></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">               <span style="color: rgb(255, 0, 0);"> Object argValue = resolveCommonArgument(methodParam, webRequest);--</span></span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt; background:#c6dbae">                              会进入resolveStandardArgument（解析标准参数）</span></font></div></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(argValue != WebArgumentResolver.</span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt"><i>UNRESOLVED</i></span></font><font face="Consolas" size="4"><span style="font-size:16pt">) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">[i] = argValue;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(defaultValue !=</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">[i] = resolveDefaultValue(defaultValue);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">{</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    Class&lt;?&gt; paramType = methodParam.getParameterType();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(Model.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isAssignableFrom(paramType) || Map.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isAssignableFrom(paramType)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(!paramType.isAssignableFrom(implicitModel.getClass())) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>throw</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>new</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">IllegalStateException(</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;Argument [&quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+ paramType.getSimpleName() +</span></font> <font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;] is of type &quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                                    </span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;Model or Map but is not assignable from the actual model. You may need to switch &quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                                    </span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;newer MVC infrastructure classes to use this argument.&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        </span><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">[i] = implicitModel;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(SessionStatus.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isAssignableFrom(paramType)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        </span><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">[i] =</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>this</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.</span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">sessionStatus</span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(HttpEntity.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isAssignableFrom(paramType)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        </span><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">[i] = resolveHttpEntityRequest(methodParam, webRequest);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(Errors.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isAssignableFrom(paramType)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>throw</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>new</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">IllegalStateException(</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;Errors/BindingResult argument declared &quot;</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">+</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                                </span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;without preceding model attribute. Check your handler method signature!&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(BeanUtils.</span><span style="font-size:16pt"><i>isSimpleProperty</i></span><span style="font-size:16pt">(paramType)) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        paramName =</span></font> <font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">{</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        attrName =</span></font> <font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><br/></div><div align="left" style="min-height: 18pt;"><div><br/></div><div>                                      <span style="font-size: 24px;">  //确定值的环节</span></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(paramName !=</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(headerName !=</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(requestBodyFound) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">[i] = resolveRequestBody(methodParam, webRequest, handler);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(cookieName !=</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(pathVarName !=</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><br/></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;">               //确定自定义类型参数的值；还要将请求中的每一个参数赋值给这个对象<br/></span></span></div></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><span style="color: rgb(227, 0, 0);"><font face="Consolas" size="4"><span style="font-size:16pt"><b>else</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(attrName !=</span></font> <font face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">) {</span></font></span></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                WebDataBinder binder =</span></font></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                        resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>boolean</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">assignBindingResult = (</span><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">.</span></font><font color="#0000C0" face="Consolas" size="4"><span style="font-size:16pt">length</span></font> <font face="Consolas" size="4"><span style="font-size:16pt">&gt; i + 1 &amp;&amp; Errors.</span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>class</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">.isAssignableFrom(paramTypes[i + 1]));</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(binder.getTarget() !=</span></font> <font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>null</b></span></font><font face="Consolas" size="4"><span style="font-size:16pt">) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    doBind(binder, webRequest, validate, validationHints, !assignBindingResult);</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">[i] = binder.getTarget();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>if</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">(assignBindingResult) {</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    </span><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">[i + 1] = binder.getBindingResult();</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                    i++;</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                }</span></font></div><div align="left" style="min-height: 11pt;"><font face="Consolas" size="4"><span style="font-size:16pt">                implicitModel.putAll(binder.getBindingResult().getModel());</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        }</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">        </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>return</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt; background:#d4d4d4">args</span><span style="font-size:16pt">;</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">    }</span></font></div></div><div><br/></div><div><hr/></div><div><span style="font-size: 21px;">如果没有注解：</span></div><div><span style="font-size: 21px;">     1）、</span><span style="font-size: 21px;">先看是否普通参数（</span><font face="Consolas" size="4"><span style="font-size:16pt; background:#d4d4d4">resolveCommonArgument</span></font><span style="font-size: 21px;">）；----就是确定当前的参数是否是原生API；</span></div><div align="left" style="min-height: 18pt;"><div style="-en-codeblock: true; box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial;"><div>@Override</div><div>        protected Object resolveStandardArgument(Class&lt;?&gt; parameterType, NativeWebRequest webRequest) throws Exception {</div><div>            HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);</div><div>            HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);</div><div><br/></div><div>            if (ServletRequest.class.isAssignableFrom(parameterType) ||</div><div>                    MultipartRequest.class.isAssignableFrom(parameterType)) {</div><div>                Object nativeRequest = webRequest.getNativeRequest(parameterType);</div><div>                if (nativeRequest == null) {</div><div>                    throw new IllegalStateException(</div><div>                            &quot;Current request is not of type [&quot; + parameterType.getName() + &quot;]: &quot; + request);</div><div>                }</div><div>                return nativeRequest;</div><div>            }</div><div>            else if (ServletResponse.class.isAssignableFrom(parameterType)) {</div><div>                this.responseArgumentUsed = true;</div><div>                Object nativeResponse = webRequest.getNativeResponse(parameterType);</div><div>                if (nativeResponse == null) {</div><div>                    throw new IllegalStateException(</div><div>                            &quot;Current response is not of type [&quot; + parameterType.getName() + &quot;]: &quot; + response);</div><div>                }</div><div>                return nativeResponse;</div><div>            }</div><div>            else if (HttpSession.class.isAssignableFrom(parameterType)) {</div><div>                return request.getSession();</div><div>            }</div><div>            else if (Principal.class.isAssignableFrom(parameterType)) {</div><div>                return request.getUserPrincipal();</div><div>            }</div><div>            else if (Locale.class.equals(parameterType)) {</div><div>                return RequestContextUtils.getLocale(request);</div><div>            }</div><div>            else if (InputStream.class.isAssignableFrom(parameterType)) {</div><div>                return request.getInputStream();</div><div>            }</div><div>            else if (Reader.class.isAssignableFrom(parameterType)) {</div><div>                return request.getReader();</div><div>            }</div><div>            else if (OutputStream.class.isAssignableFrom(parameterType)) {</div><div>                this.responseArgumentUsed = true;</div><div>                return response.getOutputStream();</div><div>            }</div><div>            else if (Writer.class.isAssignableFrom(parameterType)) {</div><div>                this.responseArgumentUsed = true;</div><div>                return response.getWriter();</div><div>            }</div><div>            return super.resolveStandardArgument(parameterType, webRequest);</div><div>        }</div></div><div><span style="font-size: 21px;">          2）、判断是否是Model或者是Map旗下的，如果是将之前创建的隐含模型直接赋值给这个参数；</span></div><div><span style="font-size: 21px;"><br/></span></div><div><hr/></div><div><span style="font-size: 21px;">方法上标注的ModelAttribute注解如果有value值   </span></div><div><span style="font-size: 21px;">@ModelAttribute(&quot;abc&quot;)</span></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt; background:#e8f2fe">hahaMyModelAttribute()</span></font></div></div><div><span style="font-size: 21px;">        标了 ：  attrName=&quot;abc&quot;</span></div><div><span style="font-size: 21px;">        没标：attrName=&quot;&quot;;attrName就会变为返回值类型首字母小写，比如void ,或者book;</span></div><div><span style="font-size: 21px;"><br/></span></div><div><span style="color: rgb(227, 0, 0);"><span style="font-size: 21px;">【@ModelAttribute标在方法上的另外一个作用；</span></span></div><div><span style="color: rgb(227, 0, 0);"><span style="font-size: 21px;">可以把方法运行后的返回值按照方法上</span><span style="font-size: 21px;">@ModelAttribute(&quot;abc&quot;)指定的key放到隐含模型中；</span></span></div><div><span style="color: rgb(227, 0, 0);"><span style="font-size: 21px; line-height: 30px;">如果没有指定这个key；就用返回值类型的首字母小写】</span></span></div><div align="left" style="min-height: 18pt;"><div><font color="#010101" face="Consolas" size="4"><span style="font-size:16pt">{haha=Book [id=100, bookName=西游记, author=吴承恩, stock=98, sales=10, price=98.98], void=null}</span></font></div></div></div><div><br/></div><div><hr/></div><div><font size="5"><span>如何确定方法的每一个参数的值；</span></font></div><div align="left" style="min-height: 18pt;"><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">@RequestMapping</span></font><font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;/updateBook&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">)</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">    </span></font><font color="#7F0055" face="Consolas" size="4"><span style="font-size:16pt"><b>public</b></span></font> <font face="Consolas" size="4"><span style="font-size:16pt">String updateBook(</span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">@RequestParam</span></font><font face="Consolas" size="4"><span style="font-size:16pt">(value=</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;author&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">)String author,</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            Map&lt;String, Object&gt; model,</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            HttpServletRequest request,</span></font></div><div align="left" style="min-height: 18pt;"><font face="Consolas" size="4"><span style="font-size:16pt">            </span></font><font color="#646464" face="Consolas" size="4"><span style="font-size:16pt">@ModelAttribute</span></font><font face="Consolas" size="4"><span style="font-size:16pt">(</span></font><font color="#2A00FF" face="Consolas" size="4"><span style="font-size:16pt">&quot;haha&quot;</span></font><font face="Consolas" size="4"><span style="font-size:16pt">)Book book</span></font></div><div align="left" style="min-height: 18pt;"><div><font face="Consolas" size="4"><span style="font-size:16pt">            )</span></font></div></div><div><img src="6、SpringMVC源码_files/Image [5].png" type="image/png"/></div><div><span style="font-size: 21px;">标了注解：</span></div><div><span style="font-size: 21px;">          保存时哪个注解的详细信息；</span></div><div><span style="font-size: 21px;">          如果参数有ModelAttribute注解；</span></div><div><span style="font-size: 21px;">               拿到ModelAttribute注解的值让attrName保存</span></div><div><span style="font-size: 21px;">                    attrName=&quot;haha&quot;<br/></span></div><div><span style="font-size: 21px;">          <br/></span></div><div><span style="font-size: 21px;"><br/></span></div><div><span style="font-size: 21px;">没标注解：</span></div><div><span style="font-size: 21px;">          1）、先看是否普通参数（是否原生API）</span></div><div><span style="font-size: 21px;">               再看是否Model或者Map，如果是就传入隐含模型；</span></div><div><span style="font-size: 21px;">          2）、自定义类型的参数没有</span><span style="font-size: 21px;">ModelAttribute</span> <span style="font-size: 21px;">注解</span></div><div><span style="font-size: 21px;">                    1）、先看是否原生API</span></div><div><span style="font-size: 21px;">                    2）、再看是否Model或者Map</span></div><div><span style="font-size: 21px;">                    3）、再看是否是其他类型的比如</span><font face="Consolas" size="4"><span style="font-size:16pt; background:#e8f2fe">SessionStatus、</span></font><font face="Consolas" size="4"><span style="font-size:16pt; background:#e8f2fe">HttpEntity、</span></font><font face="Consolas" size="4"><span style="font-size:16pt; background:#e8f2fe">Errors</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="background-color: rgb(232, 242, 254);">           4)、再看是否简单类型的属性；比如是否Integer，String，基本类型</span></span></span></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="background-color: rgb(232, 242, 254);">                    如果是</span></span></span><font face="Consolas" size="4"><span style="font-size:16pt; background:#e8f2fe">paramName=“”</span></font></div><div><span style="font-size: 16pt;"><span style="font-family: Consolas;"><span style="background-color: rgb(232, 242, 254);">           5)、attrName=&quot;&quot;；</span></span></span></div><div><font face="Consolas" size="5"><span>如果是自定义类型对象，最终会产生两个效果；</span></font></div><div><span style="font-size: 20px;"><span style="font-family: Consolas;">     1）、如果这个参数标注了ModelAttribute注解就给attrName赋值为这个注解的value值</span></span></div><div><span style="font-size: 20px;"><span style="font-family: Consolas;">     2）、如果</span></span><span style="font-size: 20px;"><span style="font-family: Consolas;">这个参数没有标注ModelAttribute注解就给attrName赋值&quot;&quot;；</span></span></div><div><span style="font-size: 20px;"><span style="font-family: Consolas;"><br/></span></span></div><div><hr/></div><div align="left" style="min-height: 18pt;"><div><font color="#7F0055" face="Consolas" size="5"><span style="line-height: 27.27272605895996px;"><b>确定自定义类型参数的值；</b></span></font></div><div><span style="font-size: 20px;"><br/></span></div><div style="-en-codeblock: true; box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial;"><div>private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam,</div><div>            ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) throws Exception {</div><div><br/></div><div>        // Bind request parameter onto object...  </div><div>        String name = attrName;</div><div>     </div><div>        if (&quot;&quot;.equals(name)) {</div><div>               //如果attrName是空串；就将参数类型的首字母小写作为值  Book book2121;name=book</div><div>            name = Conventions.getVariableNameForParameter(methodParam);</div><div>        }</div><div>        Class&lt;?&gt; paramType = methodParam.getParameterType();</div><div>       <span style="color: rgb(227, 0, 0);"> Object bindObject;确定目标对象的值</span></div><div><span style="color: rgb(227, 0, 0);">        if (implicitModel.containsKey(name)) {</span></div><div><span style="color: rgb(227, 0, 0);">            bindObject = implicitModel.get(name);</span></div><div><span style="color: rgb(227, 0, 0);">        }</span></div><div><span style="color: rgb(227, 0, 0);">        else if (this.methodResolver.isSessionAttribute(name, paramType)) {</span></div><div><span style="color: rgb(227, 0, 0);">            bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);</span></div><div><span style="color: rgb(227, 0, 0);">            if (bindObject == null) {</span></div><div><span style="color: rgb(227, 0, 0);">                raiseSessionRequiredException(&quot;Session attribute '&quot; + name + &quot;' required - not found in session&quot;);</span></div><div><span style="color: rgb(227, 0, 0);">            }</span></div><div><span style="color: rgb(227, 0, 0);">        }</span></div><div><span style="color: rgb(227, 0, 0);">        else {</span></div><div><span style="color: rgb(227, 0, 0);">            bindObject = BeanUtils.instantiateClass(paramType);</span></div><div><span style="color: rgb(227, 0, 0);">        }</span></div><div>        WebDataBinder binder = createBinder(webRequest, bindObject, name);</div><div>        initBinder(handler, name, binder, webRequest);</div><div>        return binder;</div><div>    }</div></div><div><font size="5"><span style="line-height: 26.363636016845703px;">SpringMVC确定POJO值的三步；</span></font></div><div><span style="font-size: 20px;">1、如果隐含模型中有这个key（标了ModelAttribute注解就是注解指定的value，没标就是参数类型的首字母小写）指定的值；</span></div><div><span style="font-size: 20px;">          如果有将这个值赋值给</span><span style="color: rgb(227, 0, 0);">bindObject；</span></div><div><span style="font-size: 20px;">2、如果是SessionAttributes标注的属性，就从session中拿；</span></div><div><span style="font-size: 20px;">3、如果都不是就利用反射创建对象；</span></div><div><span style="font-size: 20px;"><br/></span></div><div><hr/></div><div><font size="5"><span>两件事：</span></font></div><div><span style="font-size: 20px;">1）、运行流程简单版；</span></div><div><span style="font-size: 20px;">2）、确定方法每个参数的值；</span></div><div><span style="font-size: 20px;">          1）、标注解：保存注解的信息；最终得到这个注解应该对应解析的值；</span></div><div><span style="font-size: 20px;">         </span> <span style="font-size: 20px;">2）、没标注解：</span></div><div><span style="font-size: 20px;">                    1）、看是否是原生API；</span></div><div><span style="font-size: 20px;">                    2）、看是否是Model或者是Map，xxxx</span></div><div><span style="font-size: 20px;">                    3）、都不是，看是否是简单类型；paramName；</span></div><div><span style="font-size: 20px;">                    4）、给attrName赋值；</span><span style="font-size: 20px;">attrName（参数标了@ModelAttribute(&quot;&quot;)就是指定的，没标就是&quot;&quot;）</span></div><div><span style="font-size: 20px;">                              确定自定义类型参数：</span></div><div><span style="font-size: 20px;">                                   1）、</span><span style="font-size: 20px;">attrName使用参数的类型首字母小写；或者使用之前</span><span style="font-size: 20px;">@ModelAttribute(&quot;&quot;)的值</span></div><div><span style="font-size: 20px;">                                   2）、先看隐含模型中有每个这个attrName作为key对应的值；如果有就从隐含模型中获取并赋值</span></div><div><span style="font-size: 20px;">                                   3）、看是否是@SessionAttributes(value=&quot;haha&quot;)；标注的属性，如果是从session中拿；</span></div><div><span style="font-size: 20px;">                                                            如果拿不到就会抛异常；</span></div><div><span style="font-size: 20px;">                                   4）、不是</span><span style="font-size: 20px;">@SessionAttributes标注的，利用反射创建一个对象；</span></div><div><span style="font-size: 20px;">                   5）、拿到之前创建好的对象，使用数据绑定器(WebDataBinder)将请求中的每个数据绑定到这个对象中；<br/></span></div><div><span style="font-size: 20px;"><br/></span></div><div><span style="font-size: 20px;">                    <br/></span></div><div align="left" style="min-height: 18pt;"><div><br/></div><div style="-en-codeblock: true; box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial;"><div>  //确定值的环节</div><div>            if (paramName != null) {</div><div>                args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);</div><div>            }</div><div>            else if (headerName != null) {</div><div>                args[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);</div><div>            }</div><div>            else if (requestBodyFound) {</div><div>                args[i] = resolveRequestBody(methodParam, webRequest, handler);</div><div>            }</div><div>            else if (cookieName != null) {</div><div>                args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);</div><div>            }</div><div>            else if (pathVarName != null) {</div><div>                args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);</div><div>            }</div><div><br/></div><div>               //确定自定义类型参数的值；还要将请求中的每一个参数赋值给这个对象</div><div>            else if (attrName != null) {</div><div>                WebDataBinder binder =</div><div>                        resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);</div><div>                boolean assignBindingResult = (args.length &gt; i + 1 &amp;&amp; Errors.class.isAssignableFrom(paramTypes[i + 1]));</div><div>                if (binder.getTarget() != null) {</div><div>                    doBind(binder, webRequest, validate, validationHints, !assignBindingResult);</div><div>                }</div><div>                args[i] = binder.getTarget();</div><div>                if (assignBindingResult) {</div><div>                    args[i + 1] = binder.getBindingResult();</div><div>                    i++;</div><div>                }</div><div>                implicitModel.putAll(binder.getBindingResult().getModel());</div><div>            }</div><div>        }</div><div>        return args;</div></div><div><br/></div></div><div><span style="font-size: 20px;">       <br/></span></div></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div></span>
</div></body></html> 